package com.icesoft.api.gateway.filter;

import com.alibaba.fastjson.JSON;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.icesoft.common.exception.RRException;
import com.icesoft.common.utils.R;
import com.icesoft.common.utils.jwt.JwtUtils;
import com.netflix.zuul.ZuulFilter;
import com.netflix.zuul.context.RequestContext;
import com.netflix.zuul.exception.ZuulException;
import io.jsonwebtoken.CompressionCodecResolver;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.MalformedJwtException;
import io.jsonwebtoken.SignatureException;
import io.jsonwebtoken.impl.compression.DefaultCompressionCodecResolver;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.netflix.zuul.filters.support.FilterConstants;

import javax.servlet.http.HttpServletRequest;

/**
 * @program: icesoft-security
 * @description: Token认证过滤器
 * @author: xuefeng.gao
 * @create: 2018-11-06 13:26
 **/
@Slf4j
public class OauthAcessFilter extends ZuulFilter {


    @Value("${zuul.prefix}:")
    private String zuulPrefix;

    @Value("${gate.ignore.startWith}")
    private String startWith;
    @Value("${gate.jwt.secretkey}")
    private String secretKey;

    private static CompressionCodecResolver CODECRESOLVER = new DefaultCompressionCodecResolver();
    private static final ObjectMapper MAPPER = new ObjectMapper();

    @Override
    public String filterType() {
        return FilterConstants.PRE_TYPE;
    }

    @Override
    public int filterOrder() {
        return FilterConstants.DEBUG_FILTER_ORDER;
    }

    @Override
    public boolean shouldFilter() {
        return true;
    }

    @Override
    public Object run() throws ZuulException {
        RequestContext ctx = RequestContext.getCurrentContext();
        HttpServletRequest request = ctx.getRequest();
        final String requestUri = request.getRequestURI().substring(zuulPrefix.length());

        //1.校验请求是否拦截
        if(isStartWith(requestUri)){
            return null;
        }
        //2.校验JWT Token是否有效
        try{
            if(isValidToken(request)){
                //如果有token，则进行路由转发
                log.info("access token ok");
                return null;
            }
        }catch(RRException e){
            log.warn(e.getMessage());
            ctx.setSendZuulResponse(false);
            ctx.setResponseStatusCode(401);
            ctx.setResponseBody(JSON.toJSONString(R.error(e.getMessage())));
            ctx.getResponse().setContentType("text/html;charset=UTF-8");
            return null;
        }
        return null;
    }
    
    /**
    * 
    * param:
    **/
    private boolean isValidToken(HttpServletRequest request) throws RRException{
        boolean isValid = false;
        //从header中获取token
        String token = request.getHeader("token");
        //如果header中不存在token，则从参数中获取token
        if(StringUtils.isBlank(token)){
            token = request.getParameter("token");
        }
        //token为空
        if(StringUtils.isBlank(token)){
            throw new RRException("token不能为空");
        }
        try{
            JwtUtils.extractInfo(token,secretKey);
        } catch(MalformedJwtException e){
            throw new RRException("Token格式错误",e);
        } catch(ExpiredJwtException e){
            throw new RRException("Token已过期",e);
        }catch (SignatureException e) {
            throw new RRException("Token签名错误",e);
        } catch (Exception e) {
            throw new RRException("不支持的Token",e);
        }
        isValid = true;
        return isValid;


    }

    /**
     * URI是否以什么打头
     *
     * @param requestUri
     * @return
     */
    private boolean isStartWith(String requestUri) {
        for (String s : startWith.split(",")) {
            if (requestUri.startsWith(s)) {
                return true;
            }
        }
        return false;
    }

}
